package ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.swing.GroupLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTabbedPane;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.GroupLayout.Alignment;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;

import obj.Edge;
import obj.Junction;
import obj.Node;
import obj.Path;

import org.apache.commons.lang3.time.StopWatch;

import sim.Observer;
import util.XMLBuilder;
import util.XMLReader;

public class MainUI extends JFrame {

	private static final long serialVersionUID = 6745091049178604080L;
	int ediorPanelWidth;
	int editorPanelHeight;

	MapEditor mapEditor;
	Simulator simulator = new Simulator();
	DashBord dashBoard = new DashBord();

	public static StopWatch stopWatch = new StopWatch();
	JPanel mapEditorBase = new JPanel();
	JScrollPane mapEditorBaseScroll = new JScrollPane();
	JPanel simulatorBase = new JPanel();
	JScrollPane simulatorBaseScroll = new JScrollPane();
	private Node[][] nodesMatrix = new Node[120][60];
	List<Path> pathsList = new ArrayList<Path>();
	List<Edge> edgesList = new ArrayList<Edge>();
	List<Node> nodesList = new ArrayList<Node>();
	List<Junction> juctionList = new ArrayList<Junction>();

	private static boolean paused = false;
	private static volatile List<Observer> subscribers = new ArrayList<Observer>();
	public static JLabel lblTimeLable;

	public MainUI() {
		setTitle("traff-sim");
		Toolkit tk = Toolkit.getDefaultToolkit();
		int xSize = ((int) tk.getScreenSize().getWidth());
		int ySize = ((int) tk.getScreenSize().getHeight());
		setSize(1024, 768);
		mapEditor = new MapEditor(this.getSize());

		PixelRule columnView = new PixelRule(PixelRule.HORIZONTAL, true, false);
		PixelRule rowView = new PixelRule(PixelRule.VERTICAL, true, false);
		columnView.setPreferredWidth(1200);
		rowView.setPreferredHeight(600);

		mapEditorBase.setLayout(new BorderLayout(0, 0));
		mapEditorBase.add(mapEditorBaseScroll);
		mapEditorBaseScroll.setColumnHeaderView(columnView);
		mapEditorBaseScroll.setRowHeaderView(rowView);
		mapEditorBaseScroll.setCorner(JScrollPane.UPPER_LEFT_CORNER, new Corner(false));
		mapEditorBaseScroll.setCorner(JScrollPane.LOWER_LEFT_CORNER, new Corner(false));
		mapEditorBaseScroll.setCorner(JScrollPane.UPPER_RIGHT_CORNER, new Corner(false));
		mapEditorBaseScroll.add(mapEditor);
		mapEditorBaseScroll.setViewportView(mapEditor);
		mapEditor.setPreferredSize(new Dimension(1200, 600));
		mapEditor.setData(edgesList, nodesList, juctionList);

		PixelRule columnViewSim = new PixelRule(PixelRule.HORIZONTAL, true, true);
		PixelRule rowViewSim = new PixelRule(PixelRule.VERTICAL, true, true);
		columnViewSim.setPreferredWidth(xSize);
		rowViewSim.setPreferredHeight(ySize);
		simulatorBase.setLayout(new BorderLayout(0, 0));
		simulatorBase.add(simulatorBaseScroll);
		simulatorBaseScroll.setColumnHeaderView(columnViewSim);
		simulatorBaseScroll.setRowHeaderView(rowViewSim);
		simulatorBaseScroll.setCorner(JScrollPane.UPPER_LEFT_CORNER, new Corner(true));
		simulatorBaseScroll.setCorner(JScrollPane.LOWER_LEFT_CORNER, new Corner(true));
		simulatorBaseScroll.setCorner(JScrollPane.UPPER_RIGHT_CORNER, new Corner(true));
		simulatorBaseScroll.add(simulator);
		simulatorBaseScroll.setViewportView(simulator);
		simulator.setPreferredSize(new Dimension(1200, 600));

		final PathDialog pathDialog = new PathDialog(this, pathsList, edgesList);
		final AboutDialog about = new AboutDialog(this);

		JToolBar toolBar = new JToolBar();
		toolBar.setFloatable(false);
		toolBar.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
		toolBar.setMargin(new Insets(0, 4, 0, 4));

		JSeparator separator = new JSeparator();

		JPanel mainPanel = new JPanel();

		lblTimeLable = new JLabel();
		lblTimeLable.setBackground(Color.WHITE);
		GroupLayout groupLayout = new GroupLayout(getContentPane());
		groupLayout.setHorizontalGroup(groupLayout.createParallelGroup(Alignment.TRAILING).addComponent(mainPanel,
				GroupLayout.DEFAULT_SIZE, 1016, Short.MAX_VALUE).addGroup(
				Alignment.LEADING,
				groupLayout.createSequentialGroup().addComponent(toolBar, GroupLayout.PREFERRED_SIZE, 659,
						GroupLayout.PREFERRED_SIZE).addPreferredGap(ComponentPlacement.RELATED, 129, Short.MAX_VALUE)
						.addComponent(lblTimeLable, GroupLayout.PREFERRED_SIZE, 208, GroupLayout.PREFERRED_SIZE)
						.addGap(20)).addComponent(separator, GroupLayout.DEFAULT_SIZE, 1016, Short.MAX_VALUE));
		groupLayout.setVerticalGroup(groupLayout.createParallelGroup(Alignment.LEADING).addGroup(
				groupLayout.createSequentialGroup().addGroup(
						groupLayout.createParallelGroup(Alignment.LEADING).addComponent(toolBar,
								GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
								.addGroup(
										groupLayout.createSequentialGroup().addGap(12).addComponent(lblTimeLable,
												GroupLayout.PREFERRED_SIZE, 26, GroupLayout.PREFERRED_SIZE)))
						.addPreferredGap(ComponentPlacement.RELATED).addComponent(separator,
								GroupLayout.PREFERRED_SIZE, 2, GroupLayout.PREFERRED_SIZE).addPreferredGap(
								ComponentPlacement.RELATED).addComponent(mainPanel, GroupLayout.DEFAULT_SIZE, 622,
								Short.MAX_VALUE).addGap(26)));
		mainPanel.setLayout(new BorderLayout(0, 0));

		final JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
		tabbedPane.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent evt) {
				JTabbedPane pane = (JTabbedPane) evt.getSource();

				int sel = pane.getSelectedIndex();
				if (sel == 1) {
					simulator.setData(edgesList, nodesList, pathsList, juctionList, nodesMatrix);
				} else if (sel == 2) {
					dashBoard.drawTable(pathsList);
				}

			}
		});

		tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
		tabbedPane.addTab("Map Editor", mapEditorBase);
		tabbedPane.addTab("Simulator", simulatorBase);
		tabbedPane.addTab("Dashboard", dashBoard);

		mainPanel.add(tabbedPane);

		JButton btnNewFile = new JButton("");
		btnNewFile.setSize(new Dimension(20, 0));
		btnNewFile.setIcon(new ImageIcon(MainUI.class.getResource("/icons/icons22x22/document-new.png")));
		toolBar.add(btnNewFile);

		JButton button = new JButton("");
		button.setToolTipText("Open...");
		button.setIcon(new ImageIcon(MainUI.class.getResource("/icons/icons22x22/document-open.png")));
		button.setName("btnOpenFile");
		toolBar.add(button);

		JButton btnSaveFile = new JButton("");
		btnSaveFile.setToolTipText("Save");
		btnSaveFile.setIcon(new ImageIcon(MainUI.class.getResource("/icons/icons22x22/document-save.png")));
		toolBar.add(btnSaveFile);
		getContentPane().setLayout(groupLayout);

		// toolBar.addSeparator(new Dimension(20, 26));

		JButton btnPause = new JButton("");
		btnPause.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {

				paused = !paused;
				informSubscribers();

			}
		});
		btnPause.setToolTipText("Pause / Resume");
		btnPause.setIcon(new ImageIcon(MainUI.class.getResource("/icons/icons22x22/media-playback-pause.png")));
		toolBar.add(btnPause);

		JButton btnRun = new JButton("");
		btnRun.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				// System.out.println("Start Simulation");
				simulator.startSimulation();
				stopWatch.start();
			}
		});
		btnRun.setToolTipText("Play");
		btnRun.setIcon(new ImageIcon(MainUI.class.getResource("/icons/icons22x22/media-playback-start.png")));
		toolBar.add(btnRun);

		JButton btnStop = new JButton("");
		btnStop.setToolTipText("Stop");
		btnStop.setIcon(new ImageIcon(MainUI.class.getResource("/icons/icons22x22/process-stop.png")));
		toolBar.add(btnStop);

		// toolBar.addSeparator(new Dimension(20, 26));

		JButton btnHelp = new JButton("");
		btnHelp.setToolTipText("Help");
		btnHelp.setIcon(new ImageIcon(MainUI.class.getResource("/icons/icons22x22/help-browser.png")));
		toolBar.add(btnHelp);

		JButton btnDrawJunction = new JButton("Add T Junction");
		btnDrawJunction.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				mapEditor.drawTJunction();
				mapEditor.repaint();
			}
		});
		toolBar.add(btnDrawJunction);
		
		JButton btnAddPhase = new JButton("Add Phase");
		btnAddPhase.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

			}
		});
		toolBar.add(btnAddPhase);

		JMenuBar menuBar = new JMenuBar();
		setJMenuBar(menuBar);

		JMenu mnFile = new JMenu("File");
		menuBar.add(mnFile);

		JMenuItem mntmNew = new JMenuItem("New ");
		mntmNew.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK));
		mntmNew.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
			}
		});
		mntmNew.setIcon(new ImageIcon(MainUI.class.getResource("/icons/icons16x16/document-new.png")));
		mnFile.add(mntmNew);

		JMenuItem mntmOpen = new JMenuItem("Open");
		mntmOpen.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {

				JFileChooser fileopen = new JFileChooser();
				FileFilter filter = new FileNameExtensionFilter("traff-sim files", "xml");
				fileopen.addChoosableFileFilter(filter);

				int ret = fileopen.showDialog(null, "Open");

				if (ret == JFileChooser.APPROVE_OPTION) {
					File file = fileopen.getSelectedFile();
					// System.out.println(file);
					new XMLReader(nodesList, pathsList, edgesList, file, nodesMatrix);
				}

			}
		});
		mntmOpen.setIcon(new ImageIcon(MainUI.class.getResource("/icons/icons16x16/document-open.png")));
		mnFile.add(mntmOpen);

		JMenuItem mntmSave = new JMenuItem("Save");
		mntmSave.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {

				JFileChooser fileopen = new JFileChooser();
				FileFilter filter = new FileNameExtensionFilter("traff-sim files", "xml");
				fileopen.addChoosableFileFilter(filter);

				int ret = fileopen.showDialog(null, "Save");

				if (ret == JFileChooser.APPROVE_OPTION) {
					File file = fileopen.getSelectedFile();
					// System.out.println(file);
					new XMLBuilder(nodesList, pathsList, edgesList, file);
				}

			}
		});

		mntmSave.setIcon(new ImageIcon(MainUI.class.getResource("/icons/icons16x16/document-save.png")));
		mnFile.add(mntmSave);

		mnFile.addSeparator();
		JMenuItem mntmExit = new JMenuItem("Exit");
		mnFile.add(mntmExit);

		JMenu mnEdit = new JMenu("Edit");
		menuBar.add(mnEdit);

		JMenuItem mntmSetPath = new JMenuItem("Set Path");
		mntmSetPath.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				pathDialog.setVisible(true);

			}
		});
		mnEdit.add(mntmSetPath);

		JMenu mnRun = new JMenu("Run");
		menuBar.add(mnRun);

		JMenu mnOutput = new JMenu("Output");
		menuBar.add(mnOutput);

		JMenu mnHelp = new JMenu("Help");
		menuBar.add(mnHelp);

		JMenuItem mntmAbout = new JMenuItem("About");
		mntmAbout.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				about.setVisible(true);

			}
		});
		mnHelp.add(mntmAbout);

		setVisible(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);

	}

	public static synchronized void registerSubscriber(Observer subscriber) {
		subscribers.add(subscriber);
	}

	private static void informSubscribers() {
		for (Observer subscriber : subscribers) {
			subscriber.notify(paused);
		}
	}
}
